package com.yzjs.common.syslog;

import cn.hutool.json.JSONArray;
import com.yzjs.common.base.consts.DefContants;
import com.wdt.common.util.network.IPUtils;
import com.yzjs.common.base.entity.SysLogEntity;
import com.yzjs.common.exception.RRException;
import com.yzjs.common.util.BeanAttributeTrimUtil;
import com.yzjs.common.util.conversion.DateUtils;
import com.yzjs.common.util.conversion.JsonUtil;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Method;


@Aspect
@Component
@Order(-100)
public class SysLogAspect {



    private final static Logger log = LoggerFactory.getLogger("baitiaoUser");

    @Pointcut("@annotation(com.yzjs.common.syslog.SysLog)")
    public void pointCut() {}



    @Around("pointCut()")
    public Object doAround(ProceedingJoinPoint point) throws Throwable {
        //执行之前记录参数
        SysLogEntity sysLog = new SysLogEntity();
        this.saveLog(point,sysLog);
        Object result = null ;
        try {
            //执行方法记录参数
             result = point.proceed();
            sysLog.setOutputParmas(JsonUtil.obj2json(result));
            log.info(JsonUtil.obj2json(sysLog));
            return result;
        }catch (Throwable e){
            e.printStackTrace();
            StringWriter sw = new StringWriter();
            try(PrintWriter pw = new PrintWriter(sw);){
                e.printStackTrace(pw);
            }
            System.out.println(sw.toString().length());
            sysLog.setExceptionInfo(e.getMessage());

           // log.error("error: {}", e.getMessage(), e);
            log.info(JsonUtil.obj2json(sysLog));
            throw e;
        }


    }

    /**
     * 保存系统日志
     * @param point 切面
     */
    private void saveLog(ProceedingJoinPoint point,SysLogEntity sysLog ) throws Exception {
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();

        // 设置操作类型以及信息
        SysLog annotation = method.getAnnotation(SysLog.class);
        sysLog.setFunct(annotation.funct());
        sysLog.setModel(annotation.model());
        // 设置方法名
        String className = point.getTarget().getClass().getName();
        String methodName = signature.getName();
        sysLog.setMethod(className + "." + methodName + "()");
        //获取reqeust对象来 获取url,ip
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest request = sra.getRequest();
        if(request != null ){
            String url = request.getRequestURI();
            String ip = IPUtils.getIpAddr(request);
            sysLog.setSysUrl(url);
            sysLog.setIp(ip);
            //截取url
            String[] urls = url.split("/");
            if(urls.length >3){
                sysLog.setSource(urls[1]+"/"+urls[2]);
            }
        }
        // 设置方法参数
        Object[] args = point.getArgs();
        JSONArray json  = new JSONArray();
        for(int i=0;i < args.length ;i++){
            try {
                BeanAttributeTrimUtil.beanAttributeValueTrim(args[i]);
            } catch (Exception e) {
                e.printStackTrace();
            }
            json.add(args[i]);
        }
        sysLog.setInputParams(json.toJSONString(0));
        setLogCreatInfo(request,sysLog);
        if(log == null){
            throw new RRException("系统日志保存失败");
        }
    }

    private void setLogCreatInfo(HttpServletRequest request,SysLogEntity sysLog){
        sysLog.setCreateDate(DateUtils.getDate());

        //获取token并且解析出用户信息
        String token = request.getHeader(DefContants.X_ACCESS_TOKEN);
        if(StringUtils.isEmpty(token)){
            return ;
        }
        String account = "";
        Integer userId =1;
        if(StringUtils.isNotBlank(account) &&( userId != null)){
            sysLog.setCreateId(userId);
            sysLog.setAccount(account);
        }
    }


}
